# ZH Technical Documentation
Generated: 2025-05-09T15:47:34.836Z
This file contains technical reference documentation and release notes.
# API AND FUNCTION REFERENCES
## ao 模块
Source: https://cookbook_ao.arweave.net/zh/references/ao.html
版本: 0.0.3
`ao` 进程通信通过消息进行处理,每个进程用 ANS-104 DataItems 的格式接收消息,并且需要能够执行以下常见操作。
- isTrusted(msg) - 检查消息是否可信
- send(msg) - 将消息发给另一个进程
- spawn(module, msg) - 创建一个进程
这个 library 为 `ao` 开发者工具包提供了这些核心功能。开发者可以按需使用这个 library,但它是默认集成在开发者工具包里的。
## 属性
| 名称 | 描述 | 类型 |
| ----------- | -------------------------------- | ------ |
| id | 进程标识符 (TXID) | string |
| \_module | 模块标识符 (TXID) | string |
| authorities | 可信任的交易集合 | string |
| \_version | library 的版本 | string |
| env | 交易评估环境 | string |
| outbox | 传出消息和生成新进程请求的发件箱 | object |
## 方法
### send(msg: Message\
) : Message\
send 方法接收一个完整的 Message 对象,或者包含部分属性的 Message 对象作为参数。它会在这个对象上另外添加特定的 `ao` 标签,并返回一个完整的消息对象,同时将它插入到 ao.outbox.Messages 的表中。
**传入参数**
- msg
Schema
```json
{
"type": "object",
"properties": {
"Target": {
"type": "string",
"description": "Process/Wallet to send message to"
},
"Data": {
"type": "any",
"description": "data to send in message DataItem"
},
"Tags": {
"type": "object or array"
"description": "This property can be an array of name,value objects or an object"
}
}
}
```
例子 1
```lua
local message = ao.send({
Target = msg.From,
Data = "ping",
Tags = {
{
name = "Content-Type",
value = "text/plain"
}
}
})
```
例子 2
```lua
local message = ao.send({
Target = msg.From,
Data = "ping",
Tags = {
"Content-Type" = "text/plain"
}
})
```
**返回值**
Schema
```json
{
"type": "object",
"properties": {
"Target": {
"type": "string"
},
"Data": {
"type": "any"
},
"Tags": {
"type": "array"
"description": "name/value array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"value":{"type":"string"}
}
}
}
}
}
```
### spawn(module : string, spawn : Spawn\) : Spawn\
`spawn` 方法接收一个 TXID 模块作为第一个参数,以及一个完整的 Spawn 表,或者包含部分属性的 Spawn 表作为第二个参数。结果将返回一个完整的 Spawn 表。spawn 方法还会生成一个带有唯一引用标识符的 `Ref_` 标签。
**传入参数**
| 名称 | 描述 | 类型 |
| ------ | ------------------------------------------------- | ------ |
| module | TXID 是一个模块二进制文件的标识符,用于实例化进程 | string |
| spawn | 包含完整或部分 `Data` 和 `Tags` 属性的 `spawn` 表 | table |
Schema
module
```json
{
"type": "string"
}
```
spawn
```json
{
"type": "object",
"properties": {
"Data": { "type": "any" },
"Tags": {
"type": "object or array",
"description": "can be either array, or object"
}
}
}
```
**返回值**
Schema
```json
{
"type": "object",
"properties": {
"Data": { "type": "any" },
"Tags": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"value": { "type": "string" }
}
}
}
}
}
```
### isTrusted(msg : Message\) : boolean
在生成进程时,可以提供 0 个或多个 Authority 标签,ao library 会将这些值添加到 `ao` 属性中名为 `authorities` 的 table 数组中。这个数组为 ao.TN.1 提供了“权威证明”(Proof of Authority)功能。当消息到达 `handle` 方法时,开发者可以调用 `ao.isTrusted` 来验证消息是否来自可信来源。
**传入参数**
| 名称 | 描述 | 类型 |
| ---- | ---------------------------------- | ----- |
| msg | 用于检测这个进程是否可信的 Message | table |
Schema
```json
{
"type": "object",
"properties": {
"Target": {
"type": "string"
},
"Data": {
"type": "any"
},
"Tags": {
"type": "array"
"description": "name/value array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"value":{"type":"string"}
}
}
}
}
}
```
## 社区
Source: https://cookbook_ao.arweave.net/zh/references/community.html
[Autonomous Finance](https://www.autonomous.finance/)
- Autonomous Finance 是一个专注于 ao 网络内金融基础设施复杂性的研究和技术实体。
[BetterIdea](https://betteridea.dev/)
- 使用 BetterIDEa 构建更快、更智能、更高效的 AO 开发终极本地 Web IDE。
[Orbit](https://www.0rbit.co/)
- 0rbit 通过利用 ao 和 0rbit 节点的强大功能,将任何来自网络的数据提供给 ao 进程。用户向 0rbit ao 发送消息,0rbit 节点获取数据,然后用户进程接收数据。
## 定时消息(Cron Messages)
Source: https://cookbook_ao.arweave.net/zh/references/cron.html
ao 具有在指定时间间隔生成消息的能力,这个时间间隔可以是秒、分钟、小时或区块。有一个监控进程会自动解释和运行(eval)这些消息,然后通知 Process 根据时间处理(eval)这些消息。此时会产生一个实时进程,它可以与完整的 ao 网络或外部网络中的预言机进行通信。
## 在进程中设置定时消息(Cron Messages)
创建这些定时消息(Cron Messages)的最简单方法,是在 aos 控制台中生成一个新进程并定义时间间隔。
```sh
aos [myProcess] --cron 5-minutes
```
在生成新进程时,你可以在命令行中传递一个 cron 参数,后面加上你希望 cron 触发的时间间隔。如果你希望消息实时触发,你必须启动一个监控事件。在 aos 中,你只需调用`.monitor`,它会在 `mu` 上启动一个工作进程,从 `cu` 触发定时(cron) 消息。然后你的进程将会每隔 `x-间隔` 收到定时(cron)消息。
```lua
.monitor
```
如果你希望停止触发定时(cron) 消息,只需调用 `.unmonitor`,这会停止触发过程。但下次你发送消息时,生成的定时(cron) 消息仍将创建和处理进程。
## 处理定时消息
每条定时(cron) 消息都有一个值为 `Cron` 的 `Action` 标签。根据定义,[处理器](handlers.md)在每次收到定时(cron) 消息时,都会自动执行特定任务。
```lua
Handlers.add(
"CronTick", -- handler 的名称
Handlers.utils.hasMatchingTag("Action", "Cron"), -- 识别定时(cron) 消息的 handler 匹配函数
function () -- 需要定时执行的 handler 任务
-- 要执行的内容
end
)
```
定时消息(Cron Messages)是一个强大的实用工具,可以用来创建具有广泛功能的“自主代理”。
## 使用 ao 访问 Arweave 上的数据
Source: https://cookbook_ao.arweave.net/zh/references/data.html
在你的 ao 开发工作流程中,可能有时候你想要访问 arweave 上的数据。你的进程可以使用 ao 发送一条消息,然后 ao 网络会通过一个 Message 对象将数据提供给你的 Process 对象。
为了从 arweave 请求数据,你只需包含一个名为 `Load` 的 `Tag`,在该标签中,你可以使用数据的 TXID 来检索。
```lua
Send({
Target = ao.id,
Tags = {
Load = "WFM_Mi2FUNGCeP7r99XyeE3ySurt07LHxEGfW-wuIdY",
Action = "Data"
}
})
```
这条消息通过处理到达进程时,在传入消息的 `Data` 属性中,有一个 DataItem 的引用。同时,DataItem 的 `Data` 将以 base64 的类型传递。
```lua
{
Owner = "[Owner Address]"
Target = "[Process Identifier]",
Data = {
Owner = "xDKpdiZ7H9n_SsdX_CMpkybMGIdin5AUciM00mQgxRE",
Tags = {
"Content-Type": "application/json"
},
Data = "[base64]",
...
}
...
}
```
在 lua 中,你可以使用 “.base64” 模块将你的数据从 base64 解码回原始格式。
```lua
local base64 = require(".base64")
local data = base64.decode(Msg.Data.Data)
```
## 为什么从 Arweave 上面取数据
你的进程可能需要访问数据来做决策,或者你可能想要通过 `data` 加载功能,为你的进程添加特性。
## 编辑器设置
Source: https://cookbook_ao.arweave.net/zh/references/editor-setup.html
内置的 ao 函数和实用工具不太好用。为了提升你的开发体验,建议你在你常用的文本编辑器中安装 [Lua Language Server](https://luals.github.io) 扩展插件,并添加 [ao插件](https://github.com/martonlederer/ao-definitions)。它们支持所有内置的 aos [模块](../guides/aos/index.md) 和 [全局变量](../guides/aos/intro#globals)。
## VS Code
安装 [sumneko.lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) 扩展插件:
1. 在扩展市场中搜索 sumneko 的 "Lua"。
2. 下载并安装该扩展插件。
3. 打开 VS Code 命令面板,使用 `Shift + Command + P`(Mac)/ `Ctrl + Shift + P`(Windows/Linux),然后运行以下命令:
```
> Lua: Open Addon Manager
```
4. 在插件管理器中搜索 “ao”,它应该是第一个结果。点击 “启用”,然后就可以享受自动完成的功能了!
如果你不想为每个工作区重复这个过程,你可以从生成的工作区 `settings.json` 文件中复制 `Lua.workspace.library` 对象到你的全局 `settings.json` 文件中。
## 其他编辑器
1. 确认你的编辑器支持[语言服务器协议](https://microsoft.github.io/language-server-protocol/implementors/tools/)。
2. 按照 [luals.github.io](https://luals.github.io/#install) 上的指示安装 Lua 语言服务器。
3. 为语言服务器安装“ao”插件。
## Handlers (版本 0.0.3)
Source: https://cookbook_ao.arweave.net/zh/references/handlers.html
## 概览
Handlers library 提供了一种灵活的方式来管理和执行一系列基于模式的 handler。每个 handler 由一个匹配函数、一个处理函数和一个名称组成。这个 library 适用于需要根据不同的输入条件采取不同行动的场景。
## 模块结构
- `Handlers._version`: 代表 Handlers library 版本的字符串。
- `Handlers.list`: 存储注册的 handler 列表的表。
## 方法
### `Handlers.add(name, pattern, handler)`
添加一个新的 handler 或者根据名称更新已有的 handler。
### `Handlers.append(name, pattern, handle)`
在 handler 列表的末尾插入一个新的 handler。
#### 传入参数
- `pattern` (function 类型): 判断 handler 是否被执行的方法。
- `handle` (function 类型): handler 方法的执行函数。
- `name` (string 类型): handler 的唯一命名。
### `Handlers.prepend(name, pattern, handle)`
把一个新的 handler 加到 handler 列表的开头.
#### 传入参数
- 和 `handlers.append` 的一样。
### `Handlers.before(handleName)`
返回一个对象,可以在特定的 handler 前加入一个新的 handler。
#### 传入参数
- `handleName` (string 类型): 在新的 handler 加入前,需要给 handler 的命名。
#### 返回值
- 一个拥有 `add` 方法的对象,可以插入新的 handler。
### `Handlers.after(handleName)`
返回一个对象,可以在特定的 handler 后加入一个新的 handler。
#### 传入参数
- `handleName` (string 类型): 在新的 handler 加入后,需要给 handler 的命名。
#### 返回值
- 一个拥有 `add` 方法的对象,可以插入新的 handler。
### `Handlers.remove(name)`
根据名称从 handler 列表里移除一个 handler。
#### 传入参数
- `name` (string 类型): 要被移除的 handler 的名称。
### `Handlers.evaluate(msg, env)`
根据给定的消息和环境对每个 handler 进行评估。handler 按照它们在 handler 列表中出现的顺序依次调用。
#### 传入参数
- `msg` (table 类型): handler 要处理的消息。
- `env` (table 类型): handler 执行的环境。
#### 返回值
- `response` (类型取决于 handler 是否匹配): handler 的响应。如果没有匹配的 handler,返回一个默认消息。
## 使用案例
```lua
-- 定义模式和处理函数
local function myPattern(msg)
-- 判断 handler 是否被执行
end
local function myHandle(msg, env, response)
-- Handler 逻辑
end
-- 加一个新的 handler
Handlers.add("myHandler", myPattern, myHandle)
-- 评估一条消息
local response = handlers.evaluate({ key = "value" }, { envKey = "envValue" })
```
## 说明
- 根据 Handler 在 `handlers.list` 中的顺序执行
- 匹配函数返回 `0` 代表跳过 handler,返回 `-1` 代表在 handler 执行后中断,或者返回 `1` 代表继续执行下一个 handler。
- `evaluate` 方法可以从多个 handler 上连接响应。
## Handlers.utils
Handlers.utils 模块提供了两个常见的匹配模式函数和一个常见的处理函数。
- hasMatchingData(data)
- hasMatchingTag(name, value)
- reply(txt)
### Handlers.utils.hasMatchingData(data : string)
这个辅助函数返回一个需要消息参数的函数,因此你可以将它放入任何 handler 的匹配参数中。该函数会将传入消息的数据与作为参数提供的字符串进行比较。
```lua
Handlers.add("ping",
Handlers.utils.hasMatchingData("ping"),
...
)
```
如果这个进入进程的消息有设置成 ”ping" 的数据,那么这个 handler 会匹配上它,并调用处理函数。
### Handlers.hasMatchingTag(name : string, value : string)
这个辅助函数返回一个需要消息参数的函数,因此你可以将它放入 Handlers 模块的任何匹配参数中。该函数会比较 Tag 的名称和数值,如果它们相等,则调用处理函数。
```lua
Handlers.add("ping",
Handlers.utils.hasMatchingData("ping"),
...
)
```
### Handlers.reply(text : string)
这个辅助函数是一个简单的处理函数,就是将 text 的值放入发送消息的 Data 属性中。
```lua
Handlers.add("ping",
Handlers.utils.hasMatchingData("ping"),
Handlers.utils.reply("pong")
)
```
## 参考
Source: https://cookbook_ao.arweave.net/zh/references/index.html
## 目录
- [Lua](lua)
- [Web Assembly](wasm)
- [ao 模块](ao)
- [Handlers](handlers)
- [代币](token)
- [加载 Arweave 数据](data)
- [定时消息](cron)
- [编辑器设置](editor-setup)
## 认识 Lua
Source: https://cookbook_ao.arweave.net/zh/references/lua.html
### 理解 Lua
- **背景**: Lua 是一种轻量、高级、多范式的编程语言,主要用于嵌入式系统和客户端。它因效率、简洁和灵活性而闻名。
- **核心特性**: Lua 提供了强大的数据描述构造、动态类型、高效的内存管理以及对面向对象编程的良好支持。
### 上手指南
1. **安装**: 访问 [Lua 的官方网站](http://www.lua.org/download.html) ,下载并安装 Lua。
2. **环境**: 你可以使用简单的文本编辑器和命令行,或者像 ZeroBrane Studio ,或带有 Lua 插件的 Eclipse 这样的集成开发环境(IDE)。
### 基础语法和概念 (在 aos 中的)
- **Hello World**:
```lua
"Hello, World!"
```
- **变量和类型**: Lua 是动态类型的。基本类型包括 `nil`、`boolean`、`number`、`string`、`function`、`userdata`、`thread` 和 `table`。
- **控制结构**: 包括 `if`、 `while`、 `repeat...until` 和 `for`。
- **函数**: Lua 中的一等公民,支持闭包和高阶函数。
- **Tables**: Lua 中唯一的数据结构机制,可用于表示数组、集合、记录等。
### 动手试试
- **用 Lua 的交互模式进行实验**: 在你的终端中运行 `aos` 并尝试 Lua 命令。
- **写一些简单的脚本**: 创建 `.lua` 文件并使用 Lua 解释器运行它们。使用 `.load file.lua` 功能将 Lua 代码上传到你的 `aos` 进程中。
### 资源
- **官方文档**: [Lua 5.3 参考手册](https://www.lua.org/manual/5.3/)
- **在线教程**: 像 [Learn Lua](https://www.learn-lua.org/) 这样的网站非常适合进行交互式学习。
- **书籍**: 《Lua 编程》是一本全面的资源。(第一版可在 [网上](http://www.lua.org/pil/contents.html) 获取)
- **社区**: 加入像 [Lua 用户](http://lua-users.org/) 这样的论坛或社区,以获取支持和讨论。
### 最佳实践
- **保持极简**: Lua 的设计是简单灵活的。你要在代码中拥抱这种哲学。
- **性能**: 学习关于 Lua 的垃圾回收和高效利用 table 的知识。
- **集成**: 考虑 Lua 如何嵌入到其他应用程序中,特别是 C/C++ 项目中。
### 总结
Lua 是一种强大的语言,尤其在嵌入式系统和游戏开发领域。它的简单性和高效性让它成为特定用例的首选。祝你在 Lua 编程之旅中获得愉快的体验!
## ao Token 和子账本规范
Source: https://cookbook_ao.arweave.net/zh/references/token.html
**状态:** DRAFT-1
**目标网络:** ao.TN.1
该规范描述了标准 ao Token 进程所必须的消息 handler 和函数。该标准提供用户控制和转移资产的能力,资产的稀缺性由进程维护。
每个符合标准的进程会实现一个余额账本,用来对进程代表的资产所有权进行编码。标准中提供了一系列函数进行账本修改,这些函数包含安全保护代码,保护 Token 所有权的稀缺性。
此外,该规范描述了一种名为 '子账本' 的进程类型。实现子账本后,可以将一定数量的 Token 从父进程转移到相同 Token 接口规范的子进程中。如果子账本进程的 `From-Module` 得到参与者的信任,这些子账本可以直接进行交易,而无需与父进程交换消息。即使父进程在拥堵状态,参与者也能使用子进程中的 Token。如果参与者信任子账本进程,可以认为这些进程之间的余额是等价的。因此,同一个 Token 可以由任意数量的进程并行处理。
# Token 进程( Token Processes )
Token 进程可以对多种类型的消息作出响应,类型在 `Action` 标签中指定。Token 支持的所有的 `Action` 消息类型如下:
| 名称 | 描述 | 只读 |
| -------- | ------------------------------------------------------------- | ------------------ |
| Balance | 获取一个标志符(identifier) 的余额 | :heavy_check_mark: |
| Balances | 获取整个账本/账户的余额列表 | :heavy_check_mark: |
| Transfer | 函数调用者向一个或多个目标发送1个或多个单位,并选择通知目标。 | :x: |
| Mint | 如果你使用了具备 root 权限的进程,你可以增加 Token 供应量 | :x: |
在本节的其余部分中,描述了生成符合规范和 Token 进程所需的标签,描述了每个 `Action` 消息的形式和它们的结果。
## (创建请求的参数)Spawning Parameters
每个符合规范的 Token 进程在其生成消息中必须携带以下特定的参数:
| 标签 | 描述 | 有没有强制性 |
| ------------ | --------------------------------------------------- | ------------------ |
| Name | Token 的名称,也就是显示给用户的名称。 | :heavy_check_mark: |
| Ticker | Token 的缩写名称,以便快速引用。 | :heavy_check_mark: |
| Logo | 应用程序希望在 Token 旁边显示的图片,以便快速识别。 | :heavy_check_mark: |
| Denomination | 当向用户显示数量和余额时, Token 精度度量。 | :x: |
## 消息协议(Messaging Protocol)
### Balance(Target? : string)
返回目标的余额。如果未提供目标参数,返回消息发送者的余额。
`Action` 消息的例子:
```lua=
send({
Target = "{TokenProcess Identifier}",
Tags = {
Action = "Balance",
Target = "{IDENTIFIER}"
}
})
```
消息返回结果的例子:
```
{
Tags = {
Balance = "50",
Target = "LcldyO8wwiGDzC3iXzGofdO8JdR4S1_2A6Qtz-o33-0",
Ticker = "FUN"
}
}
```
### Balances()
返回 Token 中所有参与者的余额。
```lua
send({
Target = "[TokenProcess Identifier]",
Tags = {
Action = "Balances",
Limit = 1000, # TODO: Is this necessary if the user is paying for the compute and response?
Cursor? = "BalanceIdentifer"
}
})
```
消息返回结果的例子:
```lua
{
Data = {
"MV8B3MAKTsUOqyCzQ0Tsa2AR3TiWTBU1Dx0xM4MO-f4": 100,
"LcldyO8wwiGDzC3iXzGofdO8JdR4S1_2A6Qtz-o33-0": 50
}
}
```
### Transfer(Target, Quantity)
如果发送者拥有足够的余额,则向目标发送 `Quantity`,向接收者发出 `Credit-Notice`,向发送者发出 `Debit-Notice`。如果发送者余额不足,操作失败并通知发送者。
```lua
send({
Target = "[TokenProcess Identifier]",
Tags = {
{ name = "Action", value = "Transfer" },
{ name = "Recipient", value = "[ADDRESS]" },
{ name = "Quantity", value = "100" }
}
})
```
在未设置 `Cast` 时,如果发送成功,则应发送通知消息。
```lua
ao.send({
Target = "[Recipient Address]",
Tags = {
{ name = "Action", value = "Credit-Notice" },
{ name = "Sender", value = "[ADDRESS]" },
{ name = "Quantity", value = "100"}
}
})
```
接收者将从消息的 `From-Process` 标签中知道他们已收到该 Token 。
### Get-Info()
```lua
send({
Target = "{Token}",
Tags = {
Action = "Info"
}
})
```
### Mint() [optional]
实现 `Mint` 操作,允许特定用户创建更多 Token 余额。
```lua
send({
Target ="{Token Process}",
Tags = {
Action = "Mint",
Quantity = "1000"
}
})
```
# 子账本进程(Subledger Processes)
子账本必须实现 Token 合约的完整消息协议(不包括 `Mint` 操作)。子账本必须为进程实现额外的功能和生成参数。接下来描述子账本和父账本的区别。
### (创建请求的参数)Spawning Parameters
每个符合规范的子账本的进程在其创建请求的消息中必须携带以下特定参数:
| Tag | 描述 | 有没有强制性 |
| ------------ | --------------------------------- | ------------ |
| Source-Token | 这个子账本代表的根进程的 `ID`。 | :x: |
| Parent-Token | 这个子账本连接到的父进程的 `ID`。 | :x: |
### `Credit-Notice` Handler
在收到 `Credit-Notice` 消息时,符合规范的子账本进程必须检查所涉及的进程是否是 `Parent-Token`。如果是,则子账本必须将 `Sender` 的余额增加指定数量。
### Transfer(Target, Quantity)
除了常规的 `Credit-Notice` 标签外,子账本进程还必须提供 `Source-Token` 和 `Parent-Token` 两个标签。接受者如果信任子账本进程的 `Module`,用户就可以在子账本中进行 `Source-Token` 上的存款那样的转账和进行借贷动作。
修改后的 `Credit-Notice` 结构如下:
```lua
ao.send({
Target = "[Recipient Address]",
Tags = {
{ name = "Action", value = "Credit-Notice" },
{ name = "Quantity", value = "100"},
{ name = "Source-Token", value = "[ADDRESS]" },
{ name = "Parent-Token", value = "[ADDRESS]" }
}
})
```
### Withdraw(Target?, Quantity)
所有子账本必须允许余额持有者将他们的 Token 提取到父账本中。收到一个 `Action: Withdraw` 消息后,子账本必须向其 `Parent-Ledger` 发送一个 `Action` 消息,将请求的 Token 转移到调用者的地址,同时在本地扣除他们的账户。这个转移将会让调用者收到来自 `Parent-Ledger` 的 `Credit-Notice`。
```lua
send({
Target = "[TokenProcess Identifier]",
Tags = {
{ name = "Action", value = "Withdraw" },
{ name = "Recipient", value = "[ADDRESS]" },
{ name = "Quantity", value = "100" }
}
})
```
# Token 例子
> 请注意: 在实现 Token 时,消息上的所有标签必须是 "string" 类型。你可以使用 `tostring` 函数将简单类型转换为字符串。
```lua
if not balances then
balances = { [ao.id] = 100000000000000 }
end
if name ~= "Fun Coin" then
name = "Fun Coin"
end
if ticker ~= "Fun" then
ticker = "fun"
end
if denomination ~= 6 then
denomination = 6
end
-- handler 处理传入的消息
handlers.add(
"transfer",
handlers.utils.hasMatchingTag("Action", "Transfer"),
function (msg)
assert(type(msg.Tags.Recipient) == 'string', 'Recipient is required!')
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
if not balances[msg.From] then
balances[msg.From] = 0
end
if not balances[msg.Tags.Recipient] then
balances[msg.Tags.Recipient] = 0
end
local qty = tonumber(msg.Tags.Quantity)
assert(type(qty) == 'number', 'qty must be number')
-- handlers.utils.reply("Transfering qty")(msg)
if balances[msg.From] >= qty then
balances[msg.From] = balances[msg.From] - qty
balances[msg.Tags.Recipient] = balances[msg.Tags.Recipient] + qty
ao.send({
Target = msg.From,
Tags = {
Action = "Debit-Notice",
Quantity = tostring(qty)
}
})
ao.send({
Target = msg.Tags.Recipient,
Tags = {
Action = "Credit-Notice",
Quantity = tostring(qty)
}})
-- if msg.Tags.Cast and msg.Tags.Cast == "true" then
-- return
-- end
end
end
)
handlers.add(
"balance",
handlers.utils.hasMatchingTag("Action", "Balance"),
function (msg)
assert(type(msg.Tags.Target) == "string", "Target Tag is required!")
local bal = "0"
if balances[msg.Tags.Target] then
bal = tostring(balances[msg.Tags.Target])
end
ao.send({Target = msg.From, Tags = {
Target = msg.From,
Balance = bal,
Ticker = ticker or ""
}})
end
)
local json = require("json")
handlers.add(
"balances",
handlers.utils.hasMatchingTag("Action", "Balances"),
function (msg)
ao.send({
Target = msg.From,
Data = json.encode(balances)
})
end
)
handlers.add(
"info",
handlers.utils.hasMatchingTag("Action", "Info"),
function (msg)
ao.send({Target = msg.From, Tags = {
Name = name,
Ticker = ticker,
Denomination = tostring(denomination)
}})
end
)
```
## 认识 Web Assembly
Source: https://cookbook_ao.arweave.net/zh/references/wasm.html
WebAssembly(通常简称为 Wasm)是一种现代的二进制指令格式,为高级语言(如C、C++和Rust)提供了一个可迁移的编译目标。它可以支持在网络上部署客户端和服务器应用,并提供高水平的性能和效率。WebAssembly 是为了保持网络浏览器的安全性和沙盒功能而设计的,成为网络应用程序的选择之一。它是网络开发人员的关键技术,使他们能够用多种语言编写代码,并将代码编译为在浏览器中以接近原生速度运行的字节码。
WebAssembly 的重要性在于它能够弥合网络应用程序和本地应用程序之间的差距。它使得之前局限于桌面环境的复杂应用程序和游戏,能够在浏览器中以相当的性能运行。这为网络开发带来了新的可能性,包括创建高性能的网络应用程序、游戏,甚至将现有的桌面应用程序移植到网络上。WebAssembly 与 JavaScript 并行运行,通过使用更适合此类任务的语言编写性能关键组件,弥补了 JavaScript 的缺陷,从而增强了网络应用程序的功能和性能。
# Summary
Total files processed: 10